package com.study.design.demo2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 电商系统场景-->不会员等级价格不一样。
 * 模板方法模式使用场景真实再现。。。
 *
 * @author: chenhs
 * @date: Created in 20:51 2019/11/9
 **/
@Service
public class SaleService {

   /*
    public double sale(String userType, double fee) {
        // todo 一个价格，实际开发中，会很复杂，远远不止这一行代码
        if ("normal".equals(userType)) {
            return fee * 1.0;
        } else if ("vip".equals(userType)) {
            return fee * 0.8;
        } else if ("svip".equals(userType)) {
            return fee * 0.6;
        }
        return fee;
    }*/

/*
    @Autowired
    NormalCalculate normalCalculate;
    @Autowired
    VipCalculate vipCalculate;
    @Autowired
    SVipCalculate sVipCalculate;

    public double sale(String userType, double fee) {
        if ("normal".equals(userType)) {
            return normalCalculate.discount(fee);
        } else if ("vip".equals(userType)) {
            return vipCalculate.discount(fee);
        } else if ("svip".equals(userType)) {
            return sVipCalculate.discount(fee);
        }
        return fee;
    }*/

    // 定义一个Map存储 打折策略 对象(策略针对的类型(key) ->　对象本身(value))
    ConcurrentHashMap<String, ICalculate> calculateMap = new ConcurrentHashMap<>();


    /**
     * 1、修改注入方式 spring特殊功能；
     * 因为常规做法是，每一个折扣增加一种注入；不符合开闭设计原则（对扩展开放、对修改关闭）
     */
    // 构造函数中，自动注入所有的策略实现对象，List集合的形式。
    @Autowired
    public SaleService(List<ICalculate> iCalculateList) {
        for (ICalculate iCalculate : iCalculateList) {
            calculateMap.putIfAbsent(iCalculate.userType(), iCalculate);
        }
    }

    ApplicationContext applicationContext;

    /**
     * 2、替换if/else
     * todo 根据不同的用户类型，选用不同的对象，调用同样的接口方法
     *
     * @param type
     * @param fee
     * @return
     */
    // 计算费用方法
    public double sale(String type, double fee) {
        //本质来说就是一个 获取对象的 逻辑
        ICalculate iCalculate = calculateMap.get(type);
        if (iCalculate == null) {
            return fee;
        }

        return iCalculate.discount(fee);
    }

}
